<template>
  <!-- 自定义修饰符、针对只有一个原始组件的二次封装 -->
  <div class="w100 h100">
    <el-input v-bind="$attrs" v-model="inputText" ref="inputRef">
      <!-- 插槽/作用域插槽转发 -->
      <template v-for="(_, name) in $slots" #[name]="slotData" :key="name">
        <slot :name="name" v-bind="slotData || {}"> </slot>
      </template>
    </el-input>
    子组件内双向绑定值：<br />
    {{ modelValue }}<br />
    自定义修饰符情况：<br />
    {{ modelModifiers }}<br />
  </div>
</template>
<script setup>
// 防止变量透传
defineOptions({
  inheritAttrs: false,
});
import { computed, ref } from "vue";
// const props = defineProps({
/*   // // 用于接收父组件传递的 v-model 值，如果仅仅是 v-model，那么就传 modelValue。如果是 v-model:xxx 的话，就传 xxx 即可
  // v-model 利用 defineModel 后就可以省略 defineProps
  // modelValue: {
  //   type: String,
  //   default: () => "",
  // },
  // 自定义 v-model 修饰符
  // 用于接收父组件传递的 v-model 的修饰符，如果仅仅是 v-model 的修饰符，那么就传 modelModifiers。如果是 v-model:xxx 的话，就传 xxxModifiers 即可
  // v-model 修饰符使用 defineModel 后就可以省略 defineProps
  // modelModifiers: {
  //   type: Object,
  //   default: () => {},
  // }, */
// });

const inputRef = ref();
/*
  // 对外传输 v-model，V3 中 v-model 的默认值是 modelValue
  // 利用 defineModel 后就可以省略 defineEmits
  // const emit = defineEmits(["update:modelValue"]);

  // // 子组件内部双向绑定 model，相当于重写 v-model 的实现过程
  // 利用 defineModel 后就可以省略 computed 双向绑定以及修饰符了
  let inputText = computed({
    set(value) {
      let emitValue = value;
      // 为了兼容多个修饰符同时使用，需要在最后再输出 emitValue
      if (props.modelModifiers?.upper) {
        emitValue = emitValue.toUpperCase();
      }
      if (props.modelModifiers?.slice) {
        emitValue = emitValue.slice(0, 3);
      }
      emit("update:modelValue", emitValue);
    },
    get: () => {
      return props.modelValue;
    },
  });
*/

// v3.4 以上的新写法
// inputText 是子组件绑定的 v-model 值
// modifiers 是父组件传来的修饰符
const [inputText, modifiers] = defineModel({
  // 由于输入的时候就需要转化输入的值，因此转化的时候需要 set 函数中写
  set(value) {
    let emitValue = value;
    // 为了兼容多个修饰符同时使用，需要在最后再输出 emitValue
    if (modifiers?.upper) {
      emitValue = emitValue.toUpperCase();
    }
    if (modifiers?.slice) {
      emitValue = emitValue.slice(0, 3);
    }
    return emitValue;
  },
  // get 没用到，这里可以省略
  get: (val) => {
    return val;
  },
});

// 对外暴露圆组件的 ref
defineExpose({
  inputRef,
});
</script>

<style lang="scss" scoped>
.w100 {
  width: 100%;
}
.h100 {
  height: 100%;
}
</style>
